
#ifndef P2P_PEXREACTOR_HPP
#define P2P_PEXREACTOR_HPP
#include "NodeTable.hpp"
#include "Reactor.hpp"

#include <map>
#include <mutex>
#include <memory>

typedef unsigned char byte;

class Peer;

class PEXReactor:public Reactor
{
public:
    static const int kPexChannel = byte(0x00);
    static const int kDefaultMinNumOutboundPeers = 10;
    static const int kDefaultEnsurePeersPeriod   = 30; // second
    static const int kDefaultSeedDisconnectWaitPeriod = 2 * 60; // disconnect after this
	static const int kDefaultCrawlPeerInterval = 2 * 60;  // dont redial for this. TODO: back-off
	static const int kDefaultCrawlPeersPeriod = 30; // check some peers every this

	static const int kMaxAttemptsToDial = 16; // ~ 35h in total (last attempt - 18h)

    struct Option
    {
        Option(){ bzero(this, sizeof(*this)); }
        bool seedMode;
        std::vector<std::string> seeds;
        std::vector<std::string> privatePeerIDs;
    };

    PEXReactor(std::unique_ptr<NodeTable>& nodeTable, PEXReactor::Option const& option);
    void start(); //TODO: 
    std::unique_ptr<std::vector<byte>> getChannels();

    void addPeer(Peer const& peer);


private:
    std::unique_ptr<NodeTable> nodeTable_;
    int64_t ensurePeersPeriod_;

    bool seedMode_;
    std::vector<std::string> seeds_;
    std::vector<std::string> privatePeerIDs_;

    std::mutex mtx_;
    std::map<std::string, std::pair<int, muduo::Timestamp>> attemptsToDial_;
};

#endif // !P2P_PEXREACTOR_HPP
